package spe.xml;

import java.beans.PropertyChangeEvent;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import spe.model.spem.SPEMElement;
import spe.model.spem.SPERootElement;
import spe.xml.SPEXmlAdapter;

public class SPERootElementAdapter extends SPEXmlAdapter
{
	private static String[] CHILD_ELEMENTS = {
		"method-library",
		"method-plugin",
		"method-configuration",
		"activity",
		"role-definition",
		"task-definition",
		"work-product-definition",
		"tool-definition",
		"method-content-package",
		"process-package"
	};
	
	private static final String INTER_NODE_TYPE_SPACING = "\n\n\n";
	private static final String INTER_CHILD_SPACING = "\n\n\t";
	
	public SPERootElementAdapter() {
		// TODO Auto-generated constructor stub
	}
	
	@Override
	protected String getInterNodeTypeSpacing()
	{
		return INTER_NODE_TYPE_SPACING;
	}
	
	@Override
	protected String getInterChildSpacing()
	{
		return INTER_CHILD_SPACING;
	}
	
	@Override
	protected String[] getChildElements()
	{
		return CHILD_ELEMENTS;
	}
	
	@Override
	protected Map<String, String> getNodeTypes() 
	{
		if (NODE_TYPES == null) 
		{
			NODE_TYPES = new HashMap<String, String>();
			NODE_TYPES.put("method-library", "method-library");
			NODE_TYPES.put("method-plugin", "method-plugin");
			NODE_TYPES.put("method-configuration", "method-configuration");
			NODE_TYPES.put("activity", "activity");
			NODE_TYPES.put("role-definition", "role-definition");
			NODE_TYPES.put("task-definition", "task-definition");
			NODE_TYPES.put("work-product-definition", "work-product-definition");
			NODE_TYPES.put("tool-definition", "tool-definition");
			NODE_TYPES.put("method-content-package", "method-content-package");
			NODE_TYPES.put("process-package", "process-package");
			
		}
		return NODE_TYPES;
	}
	
	@Override
	protected void initialize()
	{
		super.initialize();
		SPERootElement root = (SPERootElement) getSemanticElement();
		if(root != null)
		{
			setAttribute("name", root.getName());
			setAttribute("id", root.getId());
			root.addPropertyChangeListener(this);
		}
		addElements(root.getElements());
	}
	
	@Override
	public void initialize(SPEMElement speElement)
	{
		super.initialize(speElement);
		SPERootElement root = (SPERootElement) getSemanticElement();
		Map<String, String> attrbMap = getAttributes();
		Iterator<String> iterAtts = attrbMap.keySet().iterator();
		String nextAttr;
		while(iterAtts.hasNext())
		{
			nextAttr = iterAtts.next();
			if("name".equals(nextAttr))
				root.setName(getAttribute("name"));
			
			if("id".equals(nextAttr))
				root.setName(getAttribute("id"));
		}
		root.addPropertyChangeListener(this);
		//System.out.println(String.format("[SPERootElementAdapter] %s = %s", root, speElement));
	}

	@Override
	protected void doModelUpdate(String name, String newValue)
	{
	}

	@Override
	protected void doModelAdd(spe.xml.SPEXmlAdapter child)
	{
		//String type = child.getElementType();
		SPEMElement childElement = getSemanticElementFor(child);
		SPERootElement root = (SPERootElement) getSemanticElement();
		root.addChildElement(childElement);
		//System.out.println(String.format("[SPERootElementAdapter] event %s", event.getNewValue()));
		
		//plug child element to child adapter and register it
		child.initialize(childElement); //<== pay attention to this
	}

	private SPEMElement getSemanticElementFor(SPEXmlAdapter child)
	{
		return child.getSemanticElement()!=null?child.getSemanticElement():createSemanticElementFor(child);
	}

	@Override
	protected void doModelRemove(spe.xml.SPEXmlAdapter child)
	{
		
	}

	@Override
	protected void doPropertyChange(PropertyChangeEvent event)
	{
		String propertyName = event.getPropertyName();
		if(propertyName.equals("Element"))
		{
			//System.out.println(String.format("[SPERootElementAdapter] event %s", event.getNewValue()));
			SPEMElement e = (SPEMElement) event.getNewValue();
			addElement(e);
			return;
		}
		
		if(propertyName.equals("RemoveElement"))
		{
			SPEMElement e = (SPEMElement) event.getOldValue();
			removeElement(e);
			return;
		}
		
		//System.out.println(String.format("[SPERootElementAdapter] event %s", event.getNewValue()));
	}
}
